package com.tdt.alarm.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.util.Log;

import com.tdt.alarm.model.AlarmContract.Alarm;

public class AlarmDBHelper extends SQLiteOpenHelper {

	public static final int DATABASE_VERSION = 1;
    public static final String DATABASE_NAME = "alarmclock.db";
    /**
     * Create Database
     */
	private static final String SQL_CREATE_ALARM = 
		"CREATE TABLE " + Alarm.TABLE_NAME + " (" +
		Alarm._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
		Alarm.COLUMN_NAME_ALARM_NAME + " TEXT," +
		Alarm.COLUMN_NAME_ALARM_TIME_HOUR + " INTEGER," +
		Alarm.COLUMN_NAME_ALARM_TIME_MINUTE + " INTEGER," +
		Alarm.COLUMN_NAME_ALARM_REPEAT_DAYS + " TEXT," +
		Alarm.COLUMN_NAME_ALARM_REPEAT_WEEKLY + " BOOLEAN," +
		Alarm.COLUMN_NAME_ALARM_TONE + " TEXT," +
		Alarm.COLUMN_NAME_ALARM_ENABLED + " BOOLEAN" + " )";

	/**
	 * Drop database
	 */
	private static final String SQL_DELETE_ALARM =
		    "DROP TABLE IF EXISTS " + Alarm.TABLE_NAME;

	public AlarmDBHelper(Context context) {
		super(context, DATABASE_NAME, null, DATABASE_VERSION);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(SQL_CREATE_ALARM);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		db.execSQL(SQL_DELETE_ALARM);
        onCreate(db);
	}
	
	/**
	 * Get one SetAlarm
	 * @param c
	 * @return a SetAlarm
	 */
	private SetAlarm populateModel(Cursor c) {
		
		long id = c.getLong(c.getColumnIndex(Alarm._ID));
        String name = c.getString(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_NAME));
        int hour = c.getInt(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_TIME_HOUR));
        int minute = c.getInt(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_TIME_MINUTE));
        boolean repeatWeekly = c.getInt(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_REPEAT_WEEKLY)) == 0 ? false : true;
        Uri ringTone = Uri.parse(c.getString(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_TONE)));
        boolean isEnabled = c.getInt(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_ENABLED)) == 0 ? false : true;
        boolean repeatingDays[] = new boolean[7];
        Time time = new Time(hour, minute, 0);
 
        String[] repeatingDay = c.getString(c.getColumnIndex(Alarm.COLUMN_NAME_ALARM_REPEAT_DAYS)).split(",");
        for (int i = 0; i < repeatingDays.length; ++i) {
        	repeatingDays[i] = repeatingDay[i].equals("false") ? false : true;
        }
        
        SetAlarm model = new SetAlarm(id, time, repeatingDays, name, ringTone, isEnabled, repeatWeekly);
        
        return model;
    }
 
	/**
	 * Put value of SetAlarm to ContentValues
	 * @param model
	 * @return ContentValues
	 */
    private ContentValues populateContent(SetAlarm model) {
        ContentValues values = new ContentValues();
        values.put(Alarm.COLUMN_NAME_ALARM_NAME, model.getLabel());
        values.put(Alarm.COLUMN_NAME_ALARM_TIME_HOUR, model.getTime().getHour());
        values.put(Alarm.COLUMN_NAME_ALARM_TIME_MINUTE, model.getTime().getMinute());
        values.put(Alarm.COLUMN_NAME_ALARM_REPEAT_WEEKLY, model.isRepeatWeekly());
        if(model.getRingtone() != null){
        	values.put(Alarm.COLUMN_NAME_ALARM_TONE, model.getRingtone().toString());
        } else {
        	values.put(Alarm.COLUMN_NAME_ALARM_TONE, "");
        }
        values.put(Alarm.COLUMN_NAME_ALARM_ENABLED, model.isCheckActive());
 
        String repeatingDays = "";
        for (int i = 0; i < 7; ++i) {
            repeatingDays += model.getRepeatingDay(i) + ",";
        }
        values.put(Alarm.COLUMN_NAME_ALARM_REPEAT_DAYS, repeatingDays);
 
        return values;
    }
    
    /**
     * Write a SetAlarm to DB
     * @param model
     * @return id of this SetAlarm
     */
    public long createAlarm(SetAlarm model) {
        ContentValues values = populateContent(model);
        return getWritableDatabase().insert(Alarm.TABLE_NAME, null, values);
    }
 
    /**
     * get a SetAlarm im DB by ID
     * @param id
     * @return
     */
    public SetAlarm getAlarm(long id) {
        SQLiteDatabase db = this.getReadableDatabase();
 
        String select = "SELECT * FROM " + Alarm.TABLE_NAME + " WHERE " + Alarm._ID + " = " + id;
 
        Cursor c = db.rawQuery(select, null);
 
        if (c.moveToNext()) {
            return populateModel(c);
        }
 
        return null;
    }
    
    /**
     * Update SetAlarm in DB
     * @param model
     * @return
     */
    public long updateAlarm(SetAlarm model) {
        ContentValues values = populateContent(model);
        values.put(Alarm.COLUMN_NAME_ALARM_ENABLED, model.isCheckActive());
        return getWritableDatabase().update(Alarm.TABLE_NAME, values, Alarm._ID + " = ?", new String[] { String.valueOf(model.getId()) });
    }
 
    /**
     * Delete setAlarm im DB by ID
     * @param id
     * @return how many row effect (default by 1)
     */
    public int deleteAlarm(long id) {
        return getWritableDatabase().delete(Alarm.TABLE_NAME, Alarm._ID + " = ?", new String[] { String.valueOf(id) });
    }
    
    /**
     * Get all SetAlarm in DB
     * @return
     */
    public List<SetAlarm> getAlarms() {
        SQLiteDatabase db = this.getWritableDatabase();
        if(db == null){
        	Log.i("DB Exeption", "DB is not readable !");
        	return null;
        }
        String select = "SELECT * FROM " + Alarm.TABLE_NAME;
 
        Cursor c = db.rawQuery(select, null);
 
        List<SetAlarm> alarmList = new ArrayList<SetAlarm>();
 
        while (c.moveToNext()) {
            alarmList.add(populateModel(c));
        }
 
        if (!alarmList.isEmpty()) {
        	Collections.reverse(alarmList);
            return alarmList;
        }
 
        return null;
    }
}